import { z } from 'zod'

const configSchema = z.object({
  // Server configuration
  port: z.number().min(1).max(65535).default(3000),
  host: z.string().default('0.0.0.0'),
  nodeEnv: z.enum(['development', 'production', 'test']).default('development'),
  
  // Security configuration
  adminApiKey: z.string().min(32, 'Admin API key must be at least 32 characters'),
  jwtSecret: z.string().min(32, 'JWT secret must be at least 32 characters').optional(),
  corsOrigin: z.string().url().optional(),
  
  // Plugin configuration
  pluginsDir: z.string().default('../../examples/plugins'),
  dataDir: z.string().default('./data'),
  maxPluginSize: z.string().default('10MB'),
  
  // Monitoring configuration
  enableMetrics: z.boolean().default(true),
  logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
  sentryDsn: z.string().optional(),
  
  // Audit configuration
  auditMaxBytes: z.number().default(5_000_000), // 5MB
  
  // Rate limiting
  rateLimitRequests: z.number().default(200),
  rateLimitWindow: z.number().default(60000), // 1 minute
  
  // Development flags
  devDisableAuth: z.boolean().default(false),
})

export type Config = z.infer<typeof configSchema>

function parseEnvNumber(value: string | undefined, defaultValue: number): number {
  if (!value) return defaultValue
  const parsed = Number(value)
  return isNaN(parsed) ? defaultValue : parsed
}

function parseEnvBoolean(value: string | undefined, defaultValue: boolean): boolean {
  if (!value) return defaultValue
  return value.toLowerCase() === 'true'
}

export function loadConfig(): Config {
  const rawConfig = {
    port: parseEnvNumber(process.env.PORT, 3000),
    host: process.env.HOST || '0.0.0.0',
    nodeEnv: process.env.NODE_ENV || 'development',
    adminApiKey: process.env.ADMIN_API_KEY || 'dev-admin-key-change-in-production',
    jwtSecret: process.env.JWT_SECRET,
    corsOrigin: process.env.CORS_ORIGIN,
    pluginsDir: process.env.PLUGINS_DIR || '../../examples/plugins',
    dataDir: process.env.DATA_DIR || './data',
    maxPluginSize: process.env.MAX_PLUGIN_SIZE || '10MB',
    enableMetrics: parseEnvBoolean(process.env.ENABLE_METRICS, true),
    logLevel: process.env.LOG_LEVEL || 'info',
    sentryDsn: process.env.SENTRY_DSN,
    auditMaxBytes: parseEnvNumber(process.env.AUDIT_MAX_BYTES, 5_000_000),
    rateLimitRequests: parseEnvNumber(process.env.RATE_LIMIT_REQUESTS, 200),
    rateLimitWindow: parseEnvNumber(process.env.RATE_LIMIT_WINDOW, 60000),
    devDisableAuth: parseEnvBoolean(process.env.DEV_DISABLE_AUTH, false),
  }

  try {
    return configSchema.parse(rawConfig)
  } catch (error) {
    if (error instanceof z.ZodError) {
      console.error('Configuration validation failed:')
      error.errors.forEach(err => {
        console.error(`  ${err.path.join('.')}: ${err.message}`)
      })
      process.exit(1)
    }
    throw error
  }
}

export function validateProductionConfig(config: Config): void {
  if (config.nodeEnv === 'production') {
    const issues: string[] = []
    
    if (config.adminApiKey === 'dev-admin-key-change-in-production') {
      issues.push('ADMIN_API_KEY must be changed from default value in production')
    }
    
    if (!config.jwtSecret) {
      issues.push('JWT_SECRET is required in production')
    }
    
    if (config.devDisableAuth) {
      issues.push('DEV_DISABLE_AUTH must be false in production')
    }
    
    if (issues.length > 0) {
      console.error('Production configuration issues:')
      issues.forEach(issue => console.error(`  - ${issue}`))
      process.exit(1)
    }
  }
}

// Global config instance
let configInstance: Config | null = null

export function getConfig(): Config {
  if (!configInstance) {
    configInstance = loadConfig()
    validateProductionConfig(configInstance)
  }
  return configInstance
}
